QuerySet对象说明
- QuerySet是Django中的一个特殊对象,本质上了列表是一样的,也可以将它理解为列表
- QuerySet的本质是继承了 list 类
打印SQL语句
- 方法一 -> 在settings.py中进行配置(在配置文件章节中有提到)
- 方法二 -> 指定打印那个orm的SQL语句
- .query
data = Student.objects.all()
sql = data.query
print(sql) # SELECT "app01_student"."id", "app01_student"."name", "app01_student"."age", "app01_student"."classes_id" FROM "app01_student"
添加数据
- 写法一
# 表的类.objects.create(字段名=xxx, 字段名=xxx)
Student.objects.create(username='Yeung')
- 写法二
obj = Student(username='Kevin')
obj.save()
# 或者简写
Student(username='Kevin').save()
- 写法三
dic = {'username': 'Kevin'}
Student.objects.create(**dic)
- 批量添加数据
# 表的类.objects.bulk_create(对象列表, num) -> num: 每次以num条写入数据库
class_lis = [
Classes(name='班级一'),
Classes(name='班级二'),
Classes(name='班级三'),
Classes(name='班级四'),
]
# class_lis = [Classes(name='班级{}'.format(i)) for i in range(100)]
Classes.objects.bulk_create(class_lis, 10)
- DateField()、DatetimeField()、TimeField() 字段类
- 日期字段类可以保存 字符串的日期(前提: 日期字段没有设置 auto_now_add=True) 或 日期对象(即: datetime)
- 如果日期字段保存的是字符串,那么取出来的也是字符串的日期(前提: 日期字段没有设置 auto_now_add=True,如果设置了 auto_now_add=True 那么保存的则是当前时间的日期对象,而不是你所指定的字符串的日期)
- 如果日期字段保存的是日期对象,那么取出来的也是日期对象
- 虽然可以保存字符串的日期,但是还是推荐保存日期对象
# model.py
class Book(models.Model):
title = models.CharField(max_length=15, verbose_name='书名')
price = models.IntegerField(verbose_name='价格')
publish_date = models.DateField(auto_now_add=False, verbose_name='出版日期')
# 保存的是字符串时间
obj = Book.objects.create(title='三国演义', price=100, publish_date='2018-9-1')
print(obj.publish_date, type(obj.publish_date)) # 2018-9-1 <class 'str'>
# 保存的是字符串时间,但日期字段设置了 auto_now_add=True
obj = Book.objects.create(title='三国演义', price=100, publish_date='2018-9-1')
print(obj.publish_date, type(obj.publish_date)) # 2019-06-18 <class 'datetime.date'>
# 保存的是日期对象
import datetime
obj = Book.objects.create(title='水浒装', price=50, publish_date=datetime.datetime.now())
print(obj.publish_date, type(obj.publish_date)) # 2019-06-18 15:26:34.999867 <class 'datetime.datetime'>
- FileField 或 ImageField 字段类
- 通过 FileField 或 ImageField 字段类所创建的字段,在添加数据的时候该字段一般接受一个文件对象
- 通过 FileField 或 ImageField 字段类所创建的字段接受到一个文件对象的时候,会将文件保存到 upload_to 字段属性所设置的文件夹路径下,如果配置了 media 那么文件就会保存到 media 目录下,然后将保存后的文件路径写入到该字段下
- upload_to 的相关说明:
- 如果设置了 upload_to 字段属性 和 配置了 media,那么文件就会保存在 media 目录下的 upload_to 字段属性所设置的文件夹路径里
- 如果设置了 upload_to 字段属性,没有配置 media,那么文件就会保存在 upload_to 字段属性所设置的文件夹路径里
- 如果没有设置了 upload_to 字段属性,但配置了 media,那么文件就会保存在 media 目录下
- 如果没有设置了 upload_to 字段属性,也没有配置了 media,那么文件就会保存项目根目录下
- 当 FileField 或 ImageField 字段类中设置了默认值得前提下,如果该字段接受到的不是一个文件对象而是一个None的话,那么该字段的数据不会保存 FileField 或 ImageField 字段类中所设置的默认值,而是保存一个空(即: NULL),如果想使用默认值那么就不要对该字段传任何数据
- 普通情况下的添加图片或文件数据
# models.py
class Picture(models.Model):
title = models.CharField(max_length=32, verbose_name='标题')
img = models.ImageField(upload_to='img/', verbose_name='图片')
# views.py
from app01.models import *
from django.shortcuts import render
import time
def home(request):
if request.method == 'POST':
img = request.FILES.get('img')
if img:
# 修改文件名,以时间作为文件名
img_name = img.name # 获取上传文件的文件名+后缀名
suffix = img_name.rsplit('.', 1)[1] # 获取文件后缀名
time_name = time.strftime("%Y%m%d%H%M%S")
img.name = '%s.%s' % (time_name, suffix)
Picture.objects.create(title='Kevin', img=img) # 将文件对象传递给 FileField 或 ImageField 字段
return render(request, 'home.html')
- 创建 admin 用户添加头像
# models.py
class UserInfo(AbstractUser):
avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png")
# views.py
def register(request):
if request.method == 'POST':
file_obj = request.FILES.get('avatar') # 接受一个文件对象
if file_obj: # 判断是否是一个文件对象
# avatar 字段是通过 FileField 或 ImageField 字段类所创建的
UserInfo.objects.create_user(avatar=file_obj, username='Kevin', password='123') # 将文件对象传递给 avatar 字段
else:
UserInfo.objects.create_user(username='Kevin', password='123') # 如果 file_obj 不是一个文件对象,那么不对 avatar 字段做任何操作,让 avatar 字段使用默认值
return render(request, 'register.html')
- .update_or_create()
- 判断某条数据是否存在,如果存在就对该条数据进行修改,如果不存在就进行添加(即: 如果有该条数据就进行修改,没有就添加)
- 语法: .update_or_create(字段名A=xxx, defaults={字段名: xxx, 字段名: xxx, ……})
- 以 字段名A + 字段名A的内容 作为查询条件,查询是否有该条数据,如果有就将该条数据中的值修改为 defaults 字典中对应的值,如果没有就添加该条数据
from api.models import *
import datetime
import uuid
user = UserInfo.objects.filter(username='Kevin', password='123').first()
uid = str(uuid.uuid4())
UserToken.objects.update_or_create(user=user, defaults={'token': uid, 'created': datetime.datetime.now()})
"""
代码解释:
1. 判断token表中是否存在 user字段等于user对象 的这条数据
2. 如果有: 就将该条数据中的 token 字段和 created 字段修改为 defaults 参数中所对应的值
3. 如果没有: 就在 token 表中添加一条数据(即:user字段等于user对象,token字段和 created字段 等于 defaults 参数中所对应的值)
"""
删除数据
- 先查询到要删除的数据(返回值: 对象),然后通过对象删除数据
# 查询到的对象.delete()
obj = Student.objects.get(id=2)
obj.delete()
# 或者简写
Student.objects.get(id=2).delete()
- 批量删除数据,即: 使用 filter() 查询数据(返回值: QuerySet->列表),然后对数据进行删除
- 方法一: 直接使用 .delete() 方法,对查询到的进行删除 -> 推荐使用
Student.objects.filter(age=18).delete()
- 方法二: 循环返回的QuerySet,获取到QuerySet中的对象然后再进行删除
objs = Student.objects.filter(age=18)
for i in objs:
i.delete()
修改数据
- 先查询到要修改的数据(返回值: 对象),然后通过对象修改数据
# 查询到的对象.字段名 = xxx
# 查询到的对象.save()
obj = Student.objects.get(id=1)
obj.username = 'Yeung'
obj.save()
- 批量修改数据,即:使用 filter() 查询数据(返回值: QuerySet->列表),然后对数据进行修改
- 方法一: 使用 .update(字段名=xxx, 字段名=xxx) -> 推荐使用
objs = Student.objects.filter(id=4)
objs.update(username='Aimer')
# 或者简写
Student.objects.filter(id=4).update(username='Aimer')
- 方法二: 循环返回的QuerySet,获取到QuerySet中的对象然后再进行修改
objs = Student.objects.filter(id=1)
for i in objs:
i.username = 'Yeung'
i.save()
- FileField 或 ImageField 字段类
- 通过 FileField 或 ImageField 字段类所创建的字段接受到一个文件对象的时候,会将文件保存到 upload_to 字段属性所设置的文件夹路径下,如果配置了 media 那么文件就会保存到 media 目录下,然后将保存后的文件路径写入到该字段下
- upload_to 的相关说明:
- 如果设置了 upload_to 字段属性 和 配置了 media,那么文件就会保存在 media 目录下的 upload_to 字段属性所设置的文件夹路径里
- 如果设置了 upload_to 字段属性,没有配置 media,那么文件就会保存在 upload_to 字段属性所设置的文件夹路径里
- 如果没有设置了 upload_to 字段属性,但配置了 media,那么文件就会保存在 media 目录下
- 如果没有设置了 upload_to 字段属性,也没有配置了 media,那么文件就会保存项目根目录下
- 当 FileField 或 ImageField 字段类中设置了默认值得前提下,如果该字段接受到的不是一个文件对象而是一个None的话,那么该字段的数据不会保存 FileField 或 ImageField 字段类中所设置的默认值,而是保存一个空(即: NULL),如果想使用默认值那么就不要对该字段传任何数据
- 使用 .FileField/ImageField字段对象.save(文件名, 文件对象) 修改文件
# models.py
class Picture(models.Model):
title = models.CharField(max_length=32, verbose_name='标题')
img = models.ImageField(upload_to='img/', verbose_name='图片')
# views.py
import os
import time
from app01.models import *
from django.conf import settings
from django.shortcuts import render
def home(request):
if request.method == 'POST':
picture_obj = Picture.objects.all().first()
img = request.FILES.get('img')
if img:
old_img_path = picture_obj.img.name
# 修改文件/图片
img_name = img.name # 获取上传文件的文件名+后缀名
suffix = img_name.rsplit('.', 1)[1] # 获取文件后缀名
time_name = time.strftime("%Y%m%d%H%M%S")
new_img_name = '%s.%s' % (time_name, suffix)
picture_obj.img.save(new_img_name, img)
picture_obj.save()
# 删除旧文件/图片
old_img_path_list = old_img_path.split('/')
old_img_address = os.path.join(settings.BASE_DIR, 'media', *old_img_path_list)
os.remove(old_img_address)
return render(request, 'home.html')
查询数据
1. filter() 方法支持 filter(表名__字段名的写法) 详细请查看 ORM-跨多张表查询自身的数据
2.pk 参数
- 在每一个查询出来的数据对象(即: QuerySet里面的每一个数据对象)中都会包含一个 pk 参数
- pk 参数: 代指的就是主键(即: id)
- 使用场景:
- 有时候我们的主键不是id而是 nid, pid, tid 等,这时候就可以直接通过 .pk 获取到该条数据的主键是什么
- 在模板语言中也可以使用该参数
# views.py
# 用法一
student_list = Student.objects.all()
for student in student_list:
pk_id = student.pk
print(pk_id) # 1
# 用法二
student_id = Student.objects.get(name='Kevin').pk # 2
# 用法三
student_obj = Student.objects.filter(pk=1).first()
# 用法四
student_list = Student.objects.all().values('pk', 'name')
# xxx.html
<p> {{ obj.pk }} </p>
3.查询某个字段为空的数据
- 字段名=None 就是查询该字段为空的数据
Student.objects.filter(age=18, address=None)
4.查询该表的所有数据
- 方式一: .all()
# 表的类.objects.all()
Student.objects.all() # 返回值:QuerySet -> 列表 -> <QuerySet [<Student: Student object>, <Student: Student object>]>
- 方式二: ** 动态实参
field_data = {}
Student.objects.filter(**field_data) # 返回值:QuerySet -> 列表 -> <QuerySet [<Student: Student object>, <Student: Student object>]>
- 通过循环返回值获取查询到的数据
# 通过 对象.字段名 获取查询到的数据
objs = Student.objects.all()
for i in objs:
print(i.id, i.username)
5..filter() -> 通过条件查询一堆数据
# 表的类.objects.filter(条件)
Student.objects.filter(age=18) # 返回值:QuerySet -> 列表 -> <QuerySet [<Student: Student object>, <Student: Student object>]>
- 通过循环返回值获取查询到的数据
# 通过 对象.字段名 获取查询到的数据
objs = Student.objects.filter(age=18)
for i in objs:
print(i.id, i.username)
6..get() -> 通过条件查询一条数据,没有查询到 或 查询到多条数据就会报错
# 表的类.objects.get(条件)
Student.objects.get(id=1) # 返回值: 对象 -> <Student: Student object>
- 通过 对象.字段名 获取查询到的数据
# 通过 对象.字段名 获取查询到的数据
obj = Student.objects.get(id=1)
print(obj.id, obj.username)
7..exclude() -> 查询与该条件不符的数据(通俗理解: .filter() 方法取反)
# 表的类.objects.exclude(条件)
Student.objects.exclude(id=2) # 返回值:QuerySet -> 列表 -> <QuerySet [<Student: Student object>, <Student: Student object>]>
- 通过循环返回值获取查询到的数据
# 通过 对象.字段名 获取查询到的数据
objs = Student.objects.exclude(id=2)
for i in objs:
print(i.id, i.username)
8..values('字段名','字段名') -> 只取某几列的数据
- 只取某几个字段的数据(通俗理解: 只取某几列的数据)
- .all() 和 .filter() 都可以使用 .values()
- .values() 不传任何字段名,默认获取全部字段
- 返回值: QuerySet -> 列表,且QuerySet中的值是以字典(键值对)的形式显示
# 表的类.objects.all().values('字段名', '字段名')
Student.objects.all().values('username','age') # 只取 username 字段 和 age 字段的数据
# 返回值:QuerySet -> 列表 -> <QuerySet [{'username': 'Yeung', 'age': 23}, {'username': 'Kevin', 'age': 18}, {'username': 'Eric', 'age': 22}]>
# .values() 不传任何字段名,默认获取全部字段
Student.objects.all().values()
9..values_list('字段名', '字段名') -> 只取某几列的数据
- 只取某几个字段的数据(通俗理解: 只取某几列的数据)
- .all() 和 .filter() 都可以使用 .values_list()
- .values_list() 不传任何字段名,默认获取全部字段
- 返回值: QuerySet -> 列表,且QuerySet中的值是以元祖的形式显示
- 和 values 的区别: values_list 直接返回查询到的数据且不带key,而 values 返回查询到的数据带key
# 表的类.objects.all().values_list('字段名', '字段名')
Student.objects.all().values_list('username','age') # 只取 username 字段 和 age 字段的数据
# 返回值:QuerySet -> 列表 -> <QuerySet [('Yeung', 23), ('Kevin', 18), ('Eric', 22)]>
# .values_list() 不传任何字段名,默认获取全部字段
Student.objects.all().values_list()
10..only('字段名', '字段名')-> 只取某几列的数据
- 只取某几个字段的数据(通俗理解: 只取某几列的数据)
- .all() 和 .filter() 都可以使用 .only()
- .only() 不传任何字段名,默认获取全部字段
- 返回值: QuerySet -> 列表,且QuerySet中的值是以对象的形式显示
- 和 values 的区别: only 所返回的值(queryset 中的值是对象),而 value 所返回的值(queryset 中的值是字典)
# 表的类.objects.all().only('字段名', '字段名')
student_list = Student.objects.all().only('username', 'age') # 只取 username 字段 和 age 字段的数据
print(student_list) # <QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>]>
for student in student_list:
print(student.__dict__) # {'id': 1, 'username': 'Kevin', 'age': 18, '_state': <django.db.models.base.ModelState object at 0x000002608AE065F8>}
print(student.username) # Kevin
print(student.age) # 18
print(student.address) # 横沥 -> 注意: 可以获取不是only指定的列的数据,但是不建议这样去操作,因为会增加多一次SQL查询(详细说明: student_list 获取到的是包含 username 和 age 字段的数据,如果要获取 address 字段的数据,那么django就会通过当前行的id去查询address字段的数据,这样就会增加了一次SQL查询,如果 student_list 有500条数据,在循环的时候都要获取address字段的数据,那么就会增加了500次SQL查询)
11..defer('字段名', '字段名')-> 获取不是这几列的数据,即 only 取反
- 不取这几个字段的数据(通俗理解: 获取不是这几列的数据)
- .all() 和 .filter() 都可以使用 .defer()
- .defer() 不传任何字段名,默认获取全部字段
- 返回值: QuerySet -> 列表,且QuerySet中的值是以对象的形式显示
- 和 only 的区别: defer 就是 only 的取反
- 和 values 的区别: defer 所返回的值(queryset 中的值是对象),而 value 所返回的值(queryset 中的值是字典)
# 表的类.objects.all().defer('字段名', '字段名')
student_list = Student.objects.all().defer('age', 'address') # 不取 age 字段 和 address 字段的数据
print(student_list) # <QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>]>
for student in student_list:
print(student.__dict__) # {'id': 1, 'username': 'Kevin', '_state': <django.db.models.base.ModelState object at 0x00000222907B65C0>}
print(student.username) # Kevin
print(student.address) # 横沥 -> 注意事项和only一样这里就不做说明了
12..order_by() -> 对查询的结果进行排序
- .order_by() -> 不传任何参数,默认会按照元信息中的 ordering 所设置的字段排序,如果元信息中的 ordering 属性,那么就按照id排序
- 正序 -> .order_by() 默认正序排序
- 查询所有数据然后进行正序排序
# 表的类.objects.order_by('字段名')
Student.objects.order_by('age') # 返回值:<QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>]>
# 通过循环,以 对象.字段名 的形式获取查询到的值,上面 .all()/.filter() 有举例,这里就不演示
# 等价于
Student.objects.all().order_by('age')
- 对查询的结果进行正序排序
# 表的类.objects.all/filter/exclude(条件).order_by('字段名')
Student.objects.filter(id__gt=1).order_by('age') # 查询 id 大于 1 的数据,然后进行正序排序
- 倒序
- 查询所有数据然后进行倒序排序
# 表的类.objects.order_by('-字段名')
Student.objects.order_by('-age')
# 等价于
Student.objects.all().order_by('-age')
- 对查询的结果进行倒序排序
# 表的类.objects.all/filter/exclude(条件).order_by('-字段名')
Student.objects.filter(id__gt=1).order_by('-age') # 查询 id 大于 1 的数据,然后进行倒序排序
- .order_by() 的第二个字段名参数,如果数据相同就以第二个字段参数进行二次排序
# 表的类.objects.order_by('字段名', '字段名')
Student.objects.order_by('age','-id')
# 表的类.objects.all/filter/exclude(条件).order_by('字段名', '字段名')
Student.objects.filter(id__gt=1).order_by('age','-id')
13..reverse() -> 对查询的数据进行反转排序
- 对查询的数据进行反转排序
- 注意:
- .reverse() 只能对有序的QuerySet对象进行反转
- 有序的QuerySet的意思是对查询出来的结果进行过排序的QuerySet对象
- 不对查询结果进行排序的,一般返回的都是无序的 QuerySet对象,除非在创建表时设置元信息中的ordering属性(默认对查询出来的结果进行排序)
- 使 .reverse() 生效的方法:
- 对查询结果进行一次排序,且 .order_by() 里面必须传字段名,否则 .reverse() 会无效
- 在创建表时设置元信息中ordering,默认对查询出来的结果进行排序 -> 不建议使用
- 通俗理解上面所说的意思: 一定要对查询结果进行一次排序,且 .order_by() 里面必须传字段名,否则 .reverse() 会无效
# 表的类.objects.all/filter/exclude(条件).order_by('字段名').reverse()
Student.objects.all().order_by('id').reverse() # 返回值: <QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>]>
14..distinct() -> 对查询的结果进行过滤剔除重复的数据
- 对查询的结果进行过滤剔除重复的数据
- 注意: 只要有一个字段中的数据不同(如: id)都会无效
Student.objects.values('username','address').distinct() # <QuerySet [{'address': '横沥', 'username': 'Yeung'}, {'address': '东莞', 'username': 'Kevin'}, {'address': '广东', 'username': 'Eric'}]>
15..count() -> 获取查询到的数据的总数
Student.objects.all().count() # 4
16..first() -> 返回查询到的数据中的第一条记录
Student.objects.all().first() # 返回值: 对象 -> <Student: Student object>
17..last() -> 返回查询到的数据中的最后一条记录
Student.objects.all().last() # 返回值: 对象 -> <Student: Student object>
18..exists() -> 判断是否查询到数据(通俗理解: 判断返回的QuerySet或对象中是否有值), 如果有返回 True,否则返回 False
Student.objects.all().exists() # True
Student.objects.filter(id=10).exists() # False
19..get_设置了choices参数的字段名_dispaly() -> 获取 choices 参数中 索引为1 的值
- 一般直接获取设置了 choices 参数的字段中的值的时候,只会获取 choices 参数中 索引为0 的值(因为数据库保存的就是这个值),通过 .get_设置了choices参数的字段名_dispaly() 方法可以获取 choices 参数中 索引为1 的值
- 在模板语言中也可以使用该方法只要把 () 去掉即可
# models.py
class ChoicesTable(models.Model):
education_choices = (
(1, '重点大学'),
(2, '普通本科'),
(3, '独立院校'),
(4, '民办本科'),
(5, '大专'),
(6, '民办专科'),
(7, '高中'),
(8, '其他')
)
education = models.IntegerField(verbose_name='学历', choices=education_choices, default=1)
record_choices = (
('checked', "已签到"),
('vacate', "请假"),
('late', "迟到"),
('noshow', "缺勤"),
('leave_early', "早退"),
)
record = models.CharField(verbose_name="上课纪录", choices=record_choices, default="checked", max_length=64)
data = ChoicesTable.objects.all().first()
education = data.education # 1 -> 直接获取只会获取到 choices 参数中 索引为0 的值
education = data.get_education_display() # 重点大学 -> 获取 choices 参数中 索引为1 的值
record = data.record # checked -> 直接获取只会获取到 choices 参数中 索引为0 的值
record = data.get_record_display() # 已签到 -> 获取 choices 参数中 索引为1 的值
20. 切片
- 可以对查询到的数据进行切片,前提是该数据是 QuerySet->列表 类型,而不是对象
- 切片的时候不能使用负数,否则会报错
data = Student.objects.all()[1:3]
21.查询数据的分类
返回值类型 | 方法名 |
QuerySet对象 (列表中的值是对象) | all() |
filter() | |
exclude() | |
order_by() | |
reverse() | |
distinct() | |
特殊的QuerySet对象 (列表中的值是字典类型) | values() |
特殊的QuerySet对象 (列表中的值是元祖类型) | values_list() |
对象 | get() |
first() | |
last() | |
布尔值 | exists() |
数字 | count() |
条件查询
1. 等于、不等于
# 查询 id 等于 2 的数据
Student.objects.filter(id=2)
# 等于
Student.objects.filter(id__exact=2)
# 查询 id 不等于 2 的数据
Student.objects.exclude(id=2)
2. 大于、大于等于
- 字段名__gt -> 大于 >
# 查询 id 大于 1 的数据
Student.objects.filter(id__gt=1)
- 字段名__gte -> 大于等于 >=
# 查询 id 大于等于 2 的数据
Student.objects.filter(id__gte=2)
3. 小于、小于等于
- 字段名__lt -> 小于 <
# 查询 id 小于 3 的数据
Student.objects.filter(id__lt=3)
- 字段名__lte -> 小于等于 <=
# 查询 id 小于等于 2 的数据
Student.objects.filter(id__lte=2)
4. in / not in
- 字段名__in = [xxx,xxx,xxx] -> 等同于MySQL里的 in -> 查询xxx在这堆数据里的数据
# 查询 id 在 [2, 4] 里的数据
Student.objects.filter(id__in=[2, 4])
- not in -> 使用 .exclude() 查询数据的方法实现Mysql中的 not in
# 查询 id 不在 [2, 4] 里的数据
Student.objects.exclude(id__in=[2, 4])
5. between
- 字段名__range = [num, num] -> 查询xxx字段在这个范围里的数据
# 查询 id 在 2~4 这个范围的数据
Student.objects.filter(id__range=[2, 4])
6. like 模糊查询
- 字段名__contains
- 查询xxx字段中包含 xxx 的数据
- 等同于 MySQL 中的 like '%ev%'
# 查询username字段中包含 'ev' 的数据
Student.objects.filter(username__contains='ev')
- 字段名__icontains
- 查询xxx字段中包含 xxx 的数据
- 不区分大小写
# 查询username字段中包含 'ev' 的数据,不区分大小写
Student.objects.filter(username__icontains='ev')
- 字段名__exact
- 查询xxx字段中等于 xxx 的数据
- 精准查询
- 等同于 MySQL 中的 like 'Eric'
# 查询username字段中等于 'Eric' 的数据
Student.objects.filter(username__exact='Eric')
# 等同于
Student.objects.filter(username='Eric')
- 字段名__iexact
- 查询xxx字段中等于 xxx 的数据
- 精准查询,不区分大小写
# 查询username字段中等于 'Eric' 的数据,不区分大小写
Student.objects.filter(username__iexact='eric')
- 字段名__startswith
- 查询 xxx 字段以 xxx 开头的数据
- 等同于 MySQL 中的 like 'Er%'
# 查询username字段中以 'Er' 开头的数据
Student.objects.filter(username__startswith='Er')
- 字段名__istartswith
- 查询 xxx 字段以 xxx 开头的数据
- 不区分大小写
# 查询username字段中以 'Er' 开头的数据,不区分大小写
Student.objects.filter(username__istartswith='er')
- 字段名__endswith
- 查询 xxx 字段以 xxx 结尾的数据
- 等同于 MySQL 中的 like '%ic'
# 查询username字段中以 'ic' 结尾的数据
Student.objects.filter(username__endswith='ic')
- 字段名__iendswith
- 查询 xxx 字段以 xxx 结尾的数据
- 不区分大小写
# 查询username字段中以 'ic' 结尾的数据,不区分大小写
Student.objects.filter(username__iendswith='IC')
- 字段名__year -> 查询日期字段中某一年的数据
# 查询2019年的数据
Student.objects.filter(datetime__year=2019)
# 查询 2017~2019 年的数据 -> 直接在 __year 后面拼接上 __range 范围查询就可以了
Student.objects.filter(datetime__year__range=[2017, 2019])
- 字段名__month -> 查询日期字段中某个月的数据
# 查询4月的数据
Student.objects.filter(datetime__month=4)
# 查询 2月 ~ 4月 的数据 -> 直接在 __year 后面拼接上 __range 范围查询就可以了
Student.objects.filter(datetime__month__range=[2, 4])
- 字段名__day -> 查询日期字段中某一日的数据
# 查询日期为2号的数据
Student.objects.filter(datetime__day=2)
# 查询日期 1号 ~ 4号 的数据 -> 直接在 __year 后面拼接上 __range 范围查询就可以了
Student.objects.filter(datetime__day__range=[1, 4])
7. is null / is not null
- 字段名__isnull = True/Flase
# 查询用户名不为空的数据
Student.objects.filter(username__isnull=False)
# 查询用户名为空的数据
Student.objects.filter(username__isnull=True)
在操作数据的时候字段名是字符串类型的解决方法
在日常开发中经常会获取到字符串类型的字段名,且需要通过该字符串类型的字段名去操作数据
1. 添加数据
dic = {'username': 'Kevin'}
Student.objects.create(**dic)
2. 修改数据
dic = {'name': 'Aimer'}
objs = Student.objects.filter(id=4)
objs.update(**dic)
3. 查询数据
- 方法一 -> 通过 values 或 values_list
Student.objects.values('id', 'name')
Student.objects.values_list('id', 'name')
- 方法二 -> 使用动态实参的方法
dic = {
'id__gt': 3
}
data = Student.objects.filter(**dic)
- 查询所有数据
dic = {}
data = Student.objects.filter(**dic)